import { Novel, NovelProgress } from '../types/novel';

export class NovelService {
  private static STORAGE_KEY = 'fish-mode-novels';
  private static PROGRESS_KEY = 'fish-mode-progress';
  
  private novels: Novel[] = [];
  private currentNovel: Novel | null = null;

  constructor() {
    this.loadNovels();
  }

  public async loadDefaultNovel(): Promise<void> {
    try {
      const response = await fetch('./assets/novels/sample.txt');
      const content = await response.text();
      
      const novel: Novel = {
        id: 'default-sample',
        title: '示例小说',
        content: content,
        currentPosition: 0,
        totalLength: content.length,
        lastReadTime: new Date()
      };

      this.addNovel(novel);
      this.setCurrentNovel(novel.id);
    } catch (error) {
      console.error('Failed to load default novel:', error);
    }
  }

  public addNovel(novel: Novel): void {
    const existingIndex = this.novels.findIndex(n => n.id === novel.id);
    if (existingIndex >= 0) {
      this.novels[existingIndex] = novel;
    } else {
      this.novels.push(novel);
    }
    this.saveNovels();
  }

  public removeNovel(novelId: string): void {
    this.novels = this.novels.filter(n => n.id !== novelId);
    if (this.currentNovel && this.currentNovel.id === novelId) {
      this.currentNovel = this.novels.length > 0 ? this.novels[0] : null;
    }
    this.saveNovels();
  }

  public setCurrentNovel(novelId: string): boolean {
    const novel = this.novels.find(n => n.id === novelId);
    if (novel) {
      this.currentNovel = novel;
      return true;
    }
    return false;
  }

  public getCurrentNovel(): Novel | null {
    return this.currentNovel;
  }

  public getAllNovels(): Novel[] {
    return [...this.novels];
  }

  public getNextCharacter(): string {
    if (!this.currentNovel || this.currentNovel.currentPosition >= this.currentNovel.content.length) {
      return '';
    }

    const char = this.currentNovel.content[this.currentNovel.currentPosition];
    this.currentNovel.currentPosition++;
    this.currentNovel.lastReadTime = new Date();
    
    this.saveProgress();
    return char;
  }

  public getNextWord(): string {
    if (!this.currentNovel) return '';

    let word = '';
    let char = this.getNextCharacter();
    
    while (char && !this.isWhitespace(char)) {
      word += char;
      char = this.getNextCharacter();
    }

    if (char && this.isWhitespace(char)) {
      word += char;
    }

    return word;
  }

  public resetProgress(novelId?: string): void {
    const targetNovel = novelId ? this.novels.find(n => n.id === novelId) : this.currentNovel;
    if (targetNovel) {
      targetNovel.currentPosition = 0;
      this.saveProgress();
    }
  }

  public getProgress(novelId?: string): NovelProgress | null {
    const novel = novelId ? this.novels.find(n => n.id === novelId) : this.currentNovel;
    if (!novel) return null;

    return {
      novelId: novel.id,
      position: novel.currentPosition,
      percentage: (novel.currentPosition / novel.totalLength) * 100
    };
  }

  public importFromFile(file: File): Promise<Novel> {
    return new Promise((resolve, reject) => {
      const reader = new FileReader();
      reader.onload = (e) => {
        try {
          const content = e.target?.result as string;
          const novel: Novel = {
            id: `imported-${Date.now()}`,
            title: file.name.replace(/\.[^/.]+$/, ''),
            content: content,
            currentPosition: 0,
            totalLength: content.length,
            lastReadTime: new Date()
          };
          
          this.addNovel(novel);
          resolve(novel);
        } catch (error) {
          reject(error);
        }
      };
      reader.onerror = () => reject(new Error('Failed to read file'));
      reader.readAsText(file, 'utf-8');
    });
  }

  private isWhitespace(char: string): boolean {
    return /\s/.test(char);
  }

  private loadNovels(): void {
    try {
      const stored = localStorage.getItem(NovelService.STORAGE_KEY);
      if (stored) {
        this.novels = JSON.parse(stored);
        if (this.novels.length > 0) {
          this.currentNovel = this.novels[0];
        }
      }
    } catch (error) {
      console.error('Failed to load novels from storage:', error);
      this.novels = [];
    }
  }

  private saveNovels(): void {
    try {
      localStorage.setItem(NovelService.STORAGE_KEY, JSON.stringify(this.novels));
    } catch (error) {
      console.error('Failed to save novels to storage:', error);
    }
  }

  private saveProgress(): void {
    try {
      const progress = this.novels.map(novel => ({
        id: novel.id,
        position: novel.currentPosition,
        lastReadTime: novel.lastReadTime
      }));
      localStorage.setItem(NovelService.PROGRESS_KEY, JSON.stringify(progress));
    } catch (error) {
      console.error('Failed to save progress to storage:', error);
    }
  }
}